/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.meteocal.gui;

import it.polimi.meteocal.entities.Event;
import it.polimi.meteocal.entities.Invitation;
import it.polimi.meteocal.entities.User;
import it.polimi.meteocal.sessionbeans.EventManager;
import it.polimi.meteocal.sessionbeans.NotificationManager;
import it.polimi.meteocal.sessionbeans.UserManager;
import it.polimi.meteocal.sessionbeans.WeatherManager;
import java.io.IOException;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
 
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel; 

@ManagedBean(name = "ScheduleView")
@SessionScoped
public class ScheduleView implements Serializable {
       
    @EJB
    UserManager um;
    
    @EJB
    EventManager em;
    
    @EJB
    NotificationManager nm;
    
      
    @ManagedProperty(value="#{InviteUserBean}")
    private InviteUserBean iub;
 
    private ScheduleModel eventModel;
    private ScheduleEvent event = new DefaultScheduleEvent();
    private Event myEvent;
    private User logged;
    private Date date;
    
 
    @PostConstruct
    public void init() {
        logged = um.getLoggedUser();
        eventModel = new DefaultScheduleModel();
        /* Carica tutti gli eventi nel calendario */
        List<Event> organizedEvents = em.loadOrganizedEvents(logged);
        List<Event> participantEvents = em.loadParticipantEvents(logged);
        participantEvents.addAll(organizedEvents);
               
        Iterator<Event> iterator = participantEvents.iterator();
        while(iterator.hasNext()){
            Event e = iterator.next();
            String name = e.getName();
            Date start = e.getStartHour();
            Date end = e.getEndHour();
            eventModel.addEvent(new DefaultScheduleEvent(name, start, end));
        }
    }
    
    public void initializeDialog(){
        myEvent = new Event(null, "public", "outdoor", "", null, null, "", "", "", true);
        myEvent.setOrganizerID(um.getLoggedUser());
        event = new DefaultScheduleEvent(); 
        List<User> empty = new ArrayList<>();
        iub.setSelectedUsers(empty);
    }
       
    public ScheduleModel getEventModel() {
        return eventModel;
    }
    
    public ScheduleEvent getScheduleEvent(){
        return this.event;
    }
    
    public void setScheduleEvent(ScheduleEvent e){
        this.event = e;
    }
     
    public Event getEvent() {
        if(myEvent == null) {
            myEvent = new Event();
            myEvent.setValid(true);
            myEvent.setOrganizerID(logged);
        }  
        return myEvent;
    }
    
    public void setEvent(Event e) {
        this.myEvent = e;
    }
    
    public InviteUserBean getIub(){ 
        return iub;
    }
    
    public void setIub(InviteUserBean iub){
        this.iub = iub;
    }
    
    public User getUser(){
        return logged;
    }
    
    public void setDate(Date date) {  
        this.date = date;  
    }  
  
    public Date getDate() {  
        return date;  
    }  
    
    public void showEventInCalendar(ActionEvent actionEvent) throws IOException {  
        String PFeventId = event.getId();
        List<User> invites;
        /* Nuovo evento */
        if(PFeventId == null){
            /* Salvataggio evento su db */
            em.saveNewEvent(myEvent);           
            
            /* Gestione notifica di invito a evento */
            if(iub.getSelectedUsers() != null){
                invites = iub.getSelectedUsers();
                nm.sendInvitation(myEvent, invites);
            }
            
            /* Mostra evento nel calendario */
            event = new DefaultScheduleEvent(myEvent.getName(), myEvent.getStartHour(), myEvent.getEndHour()); 
            eventModel.addEvent(event); 
            
        }
        /* Evento modificato */
        else {
            /* Salvataggio evento modificato su db */
            Event myOldEvent = em.loadEventByIde(myEvent);
            em.saveModifiedEvent(myEvent);
            
            /* Gestione varie notifiche */
            if(iub.getSelectedUsers() != null){
                invites = iub.getSelectedUsers();
                
                /* Invia notifica di modifica evento solo a chi ha accettato l'invito */
                if(!myEvent.getStartHour().equals(myOldEvent.getStartHour()) ||
                   !myEvent.getEndHour().equals(myOldEvent.getEndHour())     ||
                   !myEvent.getCity().equals(myOldEvent.getCity())   ||
                   !myEvent.getAddress().equals(myOldEvent.getAddress())){
                    nm.sendModificationNotification(myEvent);
                }              
                /* Invia notifica di invito solo a chi è appena stato aggiunto */
                nm.sendInvitation(myEvent, invites);
            }  
            
            /* Mostra evento modificato nel calendario */
            event = new DefaultScheduleEvent(myEvent.getName(), myEvent.getStartHour(), myEvent.getEndHour()); 
            event.setId(PFeventId);
            eventModel.updateEvent(event);
        }     
        event = new DefaultScheduleEvent(); 
    }
    
    public void deleteEventInCalendar(ActionEvent actionEvent){
        em.setNonValidEvent(myEvent);
        nm.sendDeletionNotification(myEvent);
        eventModel.deleteEvent(event);
    }
    
    public void dontShowEventInCalendar(ActionEvent actionEvent){
        um.setParticipation(myEvent, false);
        eventModel.deleteEvent(event);
    }
    
     
    public void onEventSelect(SelectEvent selectEvent) {
        event = (ScheduleEvent) selectEvent.getObject();
        logged = um.getLoggedUser();
        List<Event> organizedEvents = em.loadOrganizedEvents(logged);
        List<Event> participantEvents = em.loadParticipantEvents(logged);
        participantEvents.addAll(organizedEvents);
        
        /* Carico i dati dell'evento selezionato */
        Iterator<Event> iterator = participantEvents.iterator();
        boolean found = false;
        while(iterator.hasNext() && !found){
            Event e = iterator.next();
            String name = e.getName();
            Date start = e.getStartHour(); 
            Date end = e.getEndHour();  
            if(name.equals(event.getTitle()) && start.equals(event.getStartDate()) && end.equals(event.getEndDate())){
                myEvent = e;
                found = true;
            }     
        }
        /* Carico la lista di invitati a quell'evento */
        List<User> invited = myEvent.getInvitedUsers();
        iub.setSelectedUsers(invited);
    }
    
    public String checkParticipation(User u){
        String result = "";
        um.refreshUser(u);
        for(Invitation i : u.getInvitationList()){
            if(i.getEvent().equals(this.myEvent)){
                if(i.getParticipant() == true){result = "accepted"; return result;}
                else if(i.getAcceptDate() != null) {result = "declined"; return result;}
                else {result = "pending"; return result;}                      
            }        
        }
        /* If per gestire il caso di utenti appena inseriti
        ma con evento non ancora salvato */
        if(this.iub.getSelectedUsers().contains(u)){
            result = "pending";
            return result;
        }
        return result;
    }
     
    public void changeCalendarVisibility(){
        um.saveModifiedUser(logged);
    }  
    
    public boolean NotOrganizer(){
        User organizer = myEvent.getOrganizerID();
        if(um.getLoggedUser().equals(organizer)){
            return false;
        }
        else return true;
    }  
}
